package com.htjx.mall.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.htjx.mall.admin.controllers.vo.OrderQuery;
import com.htjx.mall.commons.exceptions.VersionException;
import com.htjx.mall.commons.mappers.AccountMapper;
import com.htjx.mall.commons.mappers.AlipayTradeMapper;
import com.htjx.mall.commons.mappers.OrderGroupMapper;
import com.htjx.mall.commons.mappers.OrderMapper;
import com.htjx.mall.commons.models.AlipayTrade;
import com.htjx.mall.commons.models.Order;
import com.htjx.mall.commons.models.OrderGroup;
import com.htjx.mall.commons.models.User;
import com.htjx.mall.commons.models.enums.OrderStatus;
import com.htjx.mall.commons.models.enums.SeqType;
import com.htjx.mall.commons.models.user.Account;
import com.htjx.mall.commons.utils.page.Page;
import com.htjx.mall.commons.utils.page.TinyPage;

@Service
public class OrderService {
	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private OrderGroupMapper orderGroupMapper;
	@Autowired
	private AccountMapper accountMapper;
	@Autowired
	private SequenceManager sequenceManager;
	@Autowired
	private TransactionTemplate transactionTemplate;
	@Autowired
	private AlipayTradeMapper alipayTradeMapper;
	
	public List<Long> insertOrder(final List<Order> orderList) {
		final int size = orderList.size();
		long[] seq = sequenceManager.buildBatchSeq(SeqType.Order, size);
		for(int i = 0; i < size; i ++) {
			orderList.get(i).setId(seq[i]);
		}
		
		return transactionTemplate.execute(new TransactionCallback<List<Long>>() {
			@Override
			public List<Long> doInTransaction(TransactionStatus status) {
				orderMapper.insertBatch(orderList);
				
				List<Long> orderIdList = new ArrayList<Long>();
				for(int i = 0; i < size; i++) {
					orderIdList.add(orderList.get(i).getId());
				}
				return orderIdList;
			}
		});
	}
	
	public List<Order> selectOrder(List<Long> orderIds) {
		return orderMapper.selectBatch(orderIds);
	}
	
	public List<Order> selectOrderByGroupId(long orderGroupId) {
		return orderMapper.selectByGroupId(orderGroupId);
	}
	
	public void updateOrder(final List<Order> orderList) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				// TODO Auto-generated method stub
				orderMapper.updateBatch(orderList);
			}
		});
	}
	
	public Order selectOne(long id) {
		List<Long> orderIds = new ArrayList<Long>();
		orderIds.add(id);
		
		List<Order> orderList = orderMapper.selectBatch(orderIds);
		if(orderList == null) {
			return null;
		}
		
		if(orderList.size() != 1) {
			return null;
		}
		
		return orderList.get(0);
	}
	
	public void updateOne(final Order order) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				orderMapper.updateOne(order);
			}
		});
	}
	
	public void deleteOne(final long id) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				orderMapper.deleteOne(id);
			}
		});
	}
	
	public TinyPage<Order> page(User user, OrderStatus orderStatus, TinyPage<Order> page) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("size", page.pageSize());
		params.put("offset", page.offset());
		params.put("order_status", orderStatus);
		params.put("user_id", user.getId());
		
		List<Order> result = orderMapper.page(params);
		page.setResult(result);
		int totalCount = orderMapper.pageCount(params);
		page.setTotalCount(totalCount);
		
		return page;
	}
	
	public int count(User user, OrderStatus orderStatus) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("order_status", orderStatus);
		params.put("user_id", user.getId());
		
		int totalCount = orderMapper.pageCount(params);
		return totalCount;
	}
	
	/***
	 * 插入order Group
	 * @param user
	 * @param orderGroup
	 * @return
	 */
	
	public long insertOrderGroup(User user, final OrderGroup orderGroup) {
		long[] seq = sequenceManager.buildBatchSeq(SeqType.OrderGroup, 1);
		orderGroup.setId(seq[0]);
		
		final List<Order> orderList = orderGroup.getOrderList();
		for(Order order: orderList) {
			order.setOrder_group_id(orderGroup.getId());
			order.setUpdate_time(new Date());
		}
		
		return transactionTemplate.execute(new TransactionCallback<Long>() {
			@Override
			public Long doInTransaction(TransactionStatus status) {
				// TODO Auto-generated method stub
				orderGroupMapper.insertOne(orderGroup);
				orderMapper.updateBatch(orderList);
				return orderGroup.getId();
			}
		});
	}
	
	public boolean updateOrderGroup(final OrderGroup orderGroup, final AlipayTrade alipayTrade) {
		orderGroup.setAccountFrozen();
		final Account account = orderGroup.getAccount();
		
		orderGroup.setOrderListStatus();
		final List<Order> orderList = orderGroup.getOrderList();
		
		if(alipayTrade != null) {
			long[] seq = sequenceManager.buildBatchSeq(SeqType.AlipayTrade, 1);
			alipayTrade.setId(seq[0]);
			alipayTrade.setOrder_group_id(orderGroup.getId());
			orderGroup.setAlipay_trade_id(alipayTrade.getId());
		}
		
		return transactionTemplate.execute(new TransactionCallback<Boolean>() {
			@Override
			public Boolean doInTransaction(TransactionStatus status) {
				// TODO Auto-generated method stub
				int expect = orderGroupMapper.updateOne(orderGroup);
				if (expect != 1) {// 更新失败，抛出异常，数据回滚
					throw new VersionException("订单组请求数据过期");
				}
				
				expect = accountMapper.updateOne(account);
				if (expect != 1) {// 更新失败，抛出异常，数据回滚
					throw new VersionException("账户请求数据过期");
				}
				
				orderMapper.updateBatch(orderList);
				
				if(alipayTrade != null) {
					alipayTradeMapper.insertOne(alipayTrade);
				}
				return true;
			}
		});
	}
	
	/****
	 * 查询order Group by Id
	 */
	public OrderGroup selectOrderGroupById(long id) {
		return orderGroupMapper.selectOne(id);
	}
	
	public Page<Order> page(OrderQuery orderQuery, Page<Order> page) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("offset", page.getFirst() - 1);
		params.put("size", page.getPageSize());
		params.put("orderQuery", orderQuery);
		List<Order> result = orderMapper.page(params);
		page.setResult(result);
		if (page.isAutoCount()) {
			int totalCount = orderMapper.pageCount(params);
			page.setTotalCount(totalCount);
		}
		
		return page;
	}
}
